#include "xpmio.h"
#include "lsystem.h"
#include "lines.h"

int imgDimension;

extern double wtime();

void expand(Lsystem_t sysinfo, char* start, int num_iters, char* result) {
	int i, j, len;
	char buffer1[imgDimension];
	char buffer2[imgDimension];
	char* tmp = start;
	char* successor;
	char* writeto = buffer1;

	buffer1[0] = buffer2[0] = '\0';

	//printf("***Expanding %s\n", start);

	if(num_iters > 0) {
		for(j = 0; j < num_iters; j++) {
			len = strlen(tmp);
			for(i = 0; i < len; i++) {
				successor = getSuccessor(sysinfo, tmp[i]);
				if(strlen(successor) > 0) {
					strcat(writeto, successor);
				}
				else {
					strncat(writeto, tmp+i, 1);
				}
			}

			//printf("%d: %s\n", j, buffer2);

			if(j != num_iters-1) {
				if(j % 2 == 0) {
					tmp = buffer1;
					writeto = buffer2;
				}
				else {
					tmp = buffer2;
					writeto = buffer1;
				}

				writeto[0] = '\0';
			}
		}

		result[0] = '\0';
		strcpy(result, writeto);
	}
	else {
		strcpy(result, start);
	}
}

void drawLsystem(Lsystem_t sysinfo, char* system) {

    int i, j;
    float x = 0;
    float y = imgDimension-1;
    float theta = 0;
    double** img;
    int len = strlen(system);

    img = malloc(sizeof(double*)*imgDimension);

    for(i = 0; i < imgDimension; i++) {
        img[i] = malloc(sizeof(double)*imgDimension);
        for(j = 0; j < imgDimension; j++) {
            img[i][j] = 0;
        }
    }

    for(i = 0; i < len; i++) {
        if(isMove(sysinfo, system[i])) {
            movePoint(&x, &y, 10, theta);
        }
        else if(isDraw(sysinfo, system[i])) {
            //printf("drawing at %f %f\n", x, y);
            drawLine(&x, &y, 10, theta, img);
        }
        else if(system[i]  == '[') {
        }
        else if(system[i] == ']') {
        }
        else {
            theta += PI*getAngle(sysinfo, system[i])/180.0;
            //printf("theta: %f\n", theta);
        }
    }

    writeXPM(img, imgDimension, imgDimension, "test.xpm");

}

main(int argc, char** argv) {
	int i;
	int num_iters;
	char* start;
	char* result;
	char tmp[2] = "\0\0";
	char** new_successors;
	double t0, t1;

	//printf("Reading sysinfo...\n");
	Lsystem_t sysinfo = readSystem();
	//printf("Done reading sysinfo...\n\n");

	num_iters = atoi(argv[1]);
	imgDimension = atoi(argv[2]);

	result = malloc(sizeof(char)*imgDimension);
	start = malloc(sizeof(char)*imgDimension/2);

	t0 = wtime();

	//printf("start iters: %d\n", num_iters/2);
	//printf("old start: %s\n", sysinfo.start);
	expand(sysinfo, sysinfo.start, num_iters/2, start);
	//printf("new start: %s\n", start);

	new_successors = malloc(sizeof(char*)*sysinfo.num_rules);
	for(i = 0; i < sysinfo.num_rules; i++) {
		new_successors[i] = malloc(sizeof(char)*64);
		//printf("expanding %c\n", sysinfo.rule_predecessors[i]);
		tmp[0] = sysinfo.rule_predecessors[i];
		expand(sysinfo, tmp, num_iters-num_iters/2, new_successors[i]);
		//printf("%c expanded to %s\n", sysinfo.rule_predecessors[i], new_successors[i]);
	}

	//printf("old lsystem: \n");
	//printLsystem(sysinfo);
	//printf("\n");

	//printf("rule iters: %d\n", num_iters-num_iters/2);
	if(num_iters-num_iters/2 > 0) {
		for(i = 0; i < sysinfo.num_rules; i++) {
			free(sysinfo.rule_successors[i]);
		}
		free(sysinfo.rule_successors);

		sysinfo.rule_successors = new_successors;
	}

	//printf("new lsystem: \n");
	//printLsystem(sysinfo);
	//printf("\n");

	expand(sysinfo, start, 1, result);

	t1 = wtime();
	printf("Time: %f\n", t1-t0);
	//printf("%d\n%s\n", strlen(result),result);
	drawLsystem(sysinfo, result);

	return 0;
}
